package com.hulk.dryad.manage.lock.aop;


import com.hulk.dryad.common.annotation.Lockd;
import com.hulk.dryad.manage.lock.executor.LockdExecutor;
import com.hulk.dryad.manage.lock.expression.LockdKeyExpressionResolver;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

/**
 * 分布式锁aop处理器
 * @author hulk
 */
@Slf4j
public class LockdInterceptor implements MethodInterceptor {

	private static final String LOCKD_NAME_PREFIX = "LOCKD";
	private static final String LOCKD_NAME_SEPARATOR = "$";

    private static final LockdKeyExpressionResolver LOCK_KEY_GENERATOR = new LockdKeyExpressionResolver();

    private LockdExecutor lockdExecutor;

    public LockdInterceptor(@NonNull LockdExecutor lockdExecutor) {
        this.lockdExecutor = lockdExecutor;
    }

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        boolean locked = false;
        String lockKey = null;
        try {
			Lockd lock = invocation.getMethod().getAnnotation(Lockd.class);
            lockKey = LOCKD_NAME_PREFIX+LOCKD_NAME_SEPARATOR+LOCK_KEY_GENERATOR.getKeyName(invocation, lock);
            try {
                locked = lockdExecutor.acquireLock(lockKey, lock.acquireTimeout(), lock.expireTime());
            } catch (Exception e) {
                log.warn("lock failed", e);
            }
            if (locked) {
                log.debug("acquireLock success");
                return invocation.proceed();
            } else {
                log.warn("lock timeout");
            }
            return null;
        } finally {
            if (locked) {
                lockdExecutor.releaseLock(lockKey);
            }
        }
    }

}
